"""
权限服务层
处理权限相关的业务逻辑
"""
from typing import Dict, Any, Optional, Tuple, List
from fastapi import HTTPException, status

from apps.auth.models.permission import Permission
from apps.auth.models.role import Role
from apps.auth.models.user import User
from apps.auth.repositories.permission_repository import PermissionRepository
from apps.auth.repositories.user_repository import UserRepository


class PermissionService:
    """权限服务类"""
    
    @staticmethod
    async def create_permission(permission_data: Dict[str, Any]) -> Permission:
        """
        创建权限
        :param permission_data: 权限数据
        :return: 创建的权限实例
        :raises: HTTPException 如果权限标识已存在
        """
        # 检查权限标识是否存在
        if await PermissionRepository.exists_by_slug(permission_data["slug"]):
            raise HTTPException(
                status_code=status.HTTP_409_CONFLICT,
                detail="权限标识已存在"
            )
        
        # 创建权限
        permission = await PermissionRepository.create(permission_data)
        return permission
    
    @staticmethod
    async def get_permission_by_id(permission_id: int) -> Permission:
        """
        通过ID获取权限
        :param permission_id: 权限ID
        :return: 权限实例
        :raises: HTTPException 如果权限不存在
        """
        permission = await PermissionRepository.get_by_id(permission_id)
        if not permission:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"ID为{permission_id}的权限不存在"
            )
        return permission
    
    @staticmethod
    async def list_permissions(
        page: int = 1, 
        page_size: int = 10,
        search: Optional[str] = None,
        module: Optional[str] = None,
    ) -> Tuple[List[Permission], int]:
        """
        获取权限列表
        :param page: 页码
        :param page_size: 每页大小
        :param search: 搜索关键词
        :param module: 按模块过滤
        :return: 权限列表和总数
        """
        return await PermissionRepository.list_permissions(page, page_size, search, module)
    
    @staticmethod
    async def get_modules() -> List[str]:
        """
        获取所有权限模块名称
        :return: 模块名称列表
        """
        return await PermissionRepository.get_modules()
    
    @staticmethod
    async def update_permission(permission_id: int, update_data: Dict[str, Any]) -> Permission:
        """
        更新权限信息(部分更新)
        :param permission_id: 权限ID
        :param update_data: 更新数据
        :return: 更新后的权限
        :raises: HTTPException 如果权限不存在
        """
        # 获取权限
        permission = await PermissionService.get_permission_by_id(permission_id)
        
        # 如果更新数据包含slug，检查是否冲突
        if "slug" in update_data and update_data["slug"] != permission.slug:
            if await PermissionRepository.exists_by_slug(update_data["slug"]):
                raise HTTPException(
                    status_code=status.HTTP_409_CONFLICT,
                    detail="权限标识已存在"
                )
        
        # 更新权限
        updated_permission = await PermissionRepository.update(permission, update_data)
        return updated_permission
    
    @staticmethod
    async def update_permission_whole(permission_id: int, update_data: Dict[str, Any]) -> Permission:
        """
        全量更新权限信息
        :param permission_id: 权限ID
        :param update_data: 完整的更新数据
        :return: 更新后的权限
        :raises: HTTPException 如果权限不存在
        """
        # 获取权限
        permission = await PermissionService.get_permission_by_id(permission_id)
        
        # 如果更新了标识且标识已存在，则抛出异常
        if update_data["slug"] != permission.slug:
            if await PermissionRepository.exists_by_slug(update_data["slug"]):
                raise HTTPException(
                    status_code=status.HTTP_409_CONFLICT,
                    detail="权限标识已存在"
                )
        
        # 全量更新权限
        updated_permission = await PermissionRepository.update_whole(permission, update_data)
        return updated_permission
    
    @staticmethod
    async def delete_permission(permission_id: int) -> None:
        """
        软删除权限(逻辑删除)
        :param permission_id: 权限ID
        :raises: HTTPException 如果权限不存在
        """
        permission = await PermissionService.get_permission_by_id(permission_id)
        await PermissionRepository.delete(permission)
    
    @staticmethod
    async def hard_delete_permission(permission_id: int) -> None:
        """
        硬删除权限(物理删除)
        :param permission_id: 权限ID
        :raises: HTTPException 如果权限不存在
        """
        permission = await PermissionService.get_permission_by_id(permission_id)
        await PermissionRepository.hard_delete(permission)
    
    @staticmethod
    async def get_permission_roles(permission_id: int) -> List[Role]:
        """
        获取拥有指定权限的所有角色
        :param permission_id: 权限ID
        :return: 角色列表
        :raises: HTTPException 如果权限不存在
        """
        # 确保权限存在
        await PermissionService.get_permission_by_id(permission_id)
        
        return await PermissionRepository.get_permission_roles(permission_id)
    
    @staticmethod
    async def get_permission_users(permission_id: int) -> List[User]:
        """
        获取直接拥有指定权限的所有用户
        :param permission_id: 权限ID
        :return: 用户列表
        :raises: HTTPException 如果权限不存在
        """
        # 确保权限存在
        await PermissionService.get_permission_by_id(permission_id)
        
        return await PermissionRepository.get_permission_users(permission_id)
    
    @staticmethod
    async def assign_permission_to_user(permission_id: int, user_id: int) -> bool:
        """
        为用户分配直接权限
        :param permission_id: 权限ID
        :param user_id: 用户ID
        :return: 是否分配成功
        :raises: HTTPException 如果权限或用户不存在
        """
        # 确保权限存在
        await PermissionService.get_permission_by_id(permission_id)
        
        # 确保用户存在
        user_exists = await UserRepository.exists_by_id(user_id)
        if not user_exists:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"ID为{user_id}的用户不存在"
            )
        
        return await PermissionRepository.assign_to_user(permission_id, user_id)
    
    @staticmethod
    async def remove_permission_from_user(permission_id: int, user_id: int) -> bool:
        """
        移除用户的直接权限
        :param permission_id: 权限ID
        :param user_id: 用户ID
        :return: 是否移除成功
        :raises: HTTPException 如果权限或用户不存在
        """
        # 确保权限存在
        await PermissionService.get_permission_by_id(permission_id)
        
        # 确保用户存在
        user_exists = await UserRepository.exists_by_id(user_id)
        if not user_exists:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"ID为{user_id}的用户不存在"
            )
        
        return await PermissionRepository.remove_from_user(permission_id, user_id)
